package com.sunzm.dynamic_rule.service;

import com.sunzm.dynamic_rule.pojo.BufferAvailableLevel;
import com.sunzm.dynamic_rule.pojo.BufferResult;
import com.sunzm.dynamic_rule.pojo.RuleAtomicParam;
import io.lettuce.core.ClientOptions;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import io.lettuce.core.protocol.ProtocolVersion;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Duration;

/**
 * 缓存管理器
 */
public class BufferManager {
    private static final Logger logger = LoggerFactory.getLogger(BufferManager.class);

    private RedisClient redisClient;

    private StatefulRedisConnection<String, String> connection;

    private RedisCommands<String, String> commands;

    public BufferManager() {
        RedisURI redisURI = RedisURI.Builder
                .redis("192.168.1.250", 6379)
                .withPassword("SoboT321".toCharArray())
                .build();

        redisClient = RedisClient.create(redisURI);
        redisClient.setDefaultTimeout(Duration.ofSeconds(5));

        //注意：lettuce 6.X开始默认的protocolVersion是RESP3,如果redis的版本低于6,需要修改为RESP2，或者将lettuce降低版本到6以下
        ClientOptions clientOptions = ClientOptions.builder()
                .autoReconnect(true)
                //Redis 2 to Redis 5应该使用2, Redis6使用3
                .protocolVersion(ProtocolVersion.RESP2)
                .build();

        redisClient.setOptions(clientOptions);

        connection = redisClient.connect();

        commands = connection.sync();
    }

    public RedisCommands<String, String> getCommond() {

        if (!connection.isOpen()) {
            logger.info("lettuce连接已关闭,正在重新获取连接");
            connection = redisClient.connect();
        }

        if (!commands.isOpen()) {
            logger.info("lettuce commands已关闭,正在重新获取commands");
            commands = connection.sync();
        }

        return commands;
    }

    public void close() {

        if (connection != null && connection.isOpen()) {
            connection.close();
        }

        if (redisClient != null) {
            redisClient.shutdown();
        }
    }

    /**
     * 获取缓存数据并返回
     *
     * @param bufferKey   缓存key
     * @param atomicParam 规则原子条件对象
     * @return 缓存数据
     */
    public BufferResult getBufferData(String bufferKey, RuleAtomicParam atomicParam) {
        BufferResult bufferResult = getBufferData(bufferKey, atomicParam.getRangeStart(),
                atomicParam.getRangeEnd(), atomicParam.getThreshold());
        return bufferResult;
    }

    /**
     * 获取缓存数据并返回
     *
     * @param bufferKey       缓存key
     * @param paramRangeStart 缓存数据时间start
     * @param paramRangeEnd   缓存数据时间end
     * @param threshold       缓存数据对应查询条件的阈值
     * @return 缓存数据结果
     */
    public BufferResult getBufferData(String bufferKey, long paramRangeStart, long paramRangeEnd, int threshold) {
        // 准备缓存返回结果实体对象
        BufferResult bufferResult = new BufferResult();
        bufferResult.setBufferAvailableLevel(BufferAvailableLevel.UN_AVL);

        /*
         *  解析缓存数据
         *  格式:   2|t1,t8
         */
        RedisCommands<String, String> redisCommand = getCommond();
        String data = redisCommand.get(bufferKey);
        // data可能为null，这里直接切，会产生空指针异常
        if (StringUtils.isBlank(data) || data.split("\\|").length < 2) return bufferResult;

        String[] split = data.split("\\|");
        String[] timeRange = split[1].split(",");

        bufferResult.setBufferKey(bufferKey);
        bufferResult.setBufferValue(Integer.parseInt(split[0]));
        bufferResult.setBufferRangeStart(Long.parseLong(timeRange[0]));
        bufferResult.setBufferRangeEnd(Long.parseLong(timeRange[1]));

        /*
         * 判断缓存有效性： 完全有效 (特殊条件下)
         */
        if (paramRangeStart <= bufferResult.getBufferRangeStart()
                && paramRangeEnd >= bufferResult.getBufferRangeEnd()
                && bufferResult.getBufferValue() >= threshold) {
            bufferResult.setBufferAvailableLevel(BufferAvailableLevel.WHOLE_AVL);
            logger.warn("{} 缓存完全匹配,value为: {}", bufferKey, bufferResult.getBufferValue());
        }

        /*
         * 判断缓存有效性： 部分有效
         * TODO 重大bug修改，少了个else，逻辑就完全错误了
         */
        else if (paramRangeStart == bufferResult.getBufferRangeStart() && paramRangeEnd >= bufferResult.getBufferRangeEnd()) {
            bufferResult.setBufferAvailableLevel(BufferAvailableLevel.PARTIAL_AVL);
            // 更新外部后续查询的条件窗口起始点
            //bufferResult.setOutSideQueryStart(bufferResult.getBufferRangeEnd());
            logger.warn("count缓存部分匹配");
        }

        return bufferResult;
    }

    // 插入数据到缓存
    public void putBufferData(String bufferKey, int value, long bufferRangeStart, long bufferRangeEnd) {
        RedisCommands<String, String> redisCommand = getCommond();
        redisCommand.setex(bufferKey, 4 * Duration.ofHours(1).toMillis(),
                value + "|" + bufferRangeStart + "," + bufferRangeEnd);
    }

    public static void main(String[] args) {
        BufferManager bufferManager = new BufferManager();

        String hgetResult = bufferManager.commands.hget("boss:numberType:list:type:", "1");

        bufferManager.close();

        System.out.println(hgetResult);
    }
}
